package com.zxl.manager.privacy.utils.utils;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author chenhewen
 *
 */
public class CpuUtils {

	// =================================CPU占有率=============================
	/**
	 * 获取一个进程使用CPU的时间
	 * 
	 * @param pid
	 * @return
	 */
	public static long getAppCpuTime(int pid) {
		String[] cpuInfos = null;
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream("/proc/" + pid + "/stat")), 1000);
			String load = reader.readLine();
			cpuInfos = load.split(" ");
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
					reader = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		if (cpuInfos != null) {
			// 根据linux命令 top#print_procs 源码, 这里仅仅取utime和stime
			long appCpuTime = Long.parseLong(cpuInfos[13])
					+ Long.parseLong(cpuInfos[14])
			/* + Long.parseLong(cpuInfos[15]) + Long.parseLong(cpuInfos[16]) */;
			return appCpuTime;
		} else {
			return 0;
		}
	}

	/**
	 * 获取CPU使用的总时间
	 * 
	 * @return
	 */
	public static long getCpuTime(boolean includeIdleTime) {
		String[] cpuInfos = null;
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream("/proc/stat")), 1000);
			String load = reader.readLine();
			cpuInfos = load.split(" ");
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
					reader = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
		long totalCpu = 0;
		long idleTime = 0;

		int startIndex = 2;
		int idleStartIndex = 5;
		int idleEndIndex = 5; // 8

		for (int i = startIndex; i < cpuInfos.length; i++) {
			totalCpu += Long.parseLong(cpuInfos[i]);
		}

		if (!includeIdleTime) {
			/*
			 * totalCpu = Long.parseLong(cpuInfos[2]) +
			 * Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4]) +
			 * Long.parseLong(cpuInfos[5]) + Long.parseLong(cpuInfos[6]) +
			 * Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]);
			 */
			for (int i = idleStartIndex; i <= idleEndIndex; i++) {
				idleTime += Long.parseLong(cpuInfos[i]);
			}
			totalCpu -= idleTime;
			/*
			 * totalCpu = Long.parseLong(cpuInfos[2]) +
			 * Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4]) +
			 * Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[7]) +
			 * Long.parseLong(cpuInfos[8]);
			 */
		}

		return totalCpu;
	}

	/**
	 * 返回Map, key:包名, value:自该包启动以来累计cpu消耗, 该实现在5.0以上失效
	 * 
	 * @param context
	 * @return
	 */
	public static Map<String, Long> getSysCollectCpuUseTime(Context context) {
		Map<String, Long> map = new HashMap<String, Long>();
		ActivityManager mActivityManager = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningAppProcessInfo> mRunningProcessList = mActivityManager
				.getRunningAppProcesses();

		// 没有正在运行的应用
		if (mRunningProcessList == null) {
			// Loger.i(CpuManager.TAG, "important: [没有正在运行的应用]");
			return map;
		}

		for (RunningAppProcessInfo info : mRunningProcessList) {
			//一个小概率bug
			if (info == null) {
				continue;
			}
			
			int pid = info.pid;
			// XXX 暂时这样做, 因为同一个进程可能对应多个包名, 这里仅仅取第一个
			String pkgName = info.pkgList[0];
			// 获取对应pid下的cpu运行时间, 也就是近似成了该进程内第一个包名所对应应用的Cpu消耗时间

			long cpuRunningTime = getAppCpuTime(pid);
			if (map.containsKey(pkgName)) {
				// 同一包名在多个进程中, 累加
				map.put(pkgName, map.get(pkgName) + cpuRunningTime);
			} else {
				map.put(pkgName, cpuRunningTime);
			}
			/*
			 * if (pkgName.equals("com.cleanmaster.mguard")) {
			 * Loger.i(CpuManager.TAG,
			 * "important: [getSysCollectCpuUseTime 获得Zboost] " + pid + "/" +
			 * cpuRunningTime); }
			 */
		}

		return map;
	}

	// ========================= CPU 温度 =============================
	public static final int NOT_AVAILABLE_TEMP = -1;

	/**
	 * 
	 * @author chenhewen
	 *
	 */
	private static class TempPath {

		private final int mLength = 14;

		private String[] mCpuTemp = new String[mLength];

		private int mIndex;

		public String getNext() {

			if (mIndex < mLength) {
				return mCpuTemp[mIndex++];
			} else {
				mIndex++;
				throw new IndexOutOfBoundsException();
			}
		}

		public boolean hasNext() {
			return mIndex < mLength - 1;
		}

		public void reset() {
			mIndex = 0;
		}

		public TempPath() {
			mCpuTemp[0] = "/sys/devices/system/cpu/cpu0/cpufreq/cpu_temp";
			mCpuTemp[1] = "/sys/devices/system/cpu/cpu0/cpufreq/FakeShmoo_cpu_temp";
			mCpuTemp[2] = "/sys/class/thermal/thermal_zone1/temp";
			mCpuTemp[3] = "/sys/class/i2c-adapter/i2c-4/4-004c/temperature";
			mCpuTemp[4] = "/sys/devices/platform/tegra-i2c.3/i2c-4/4-004c/temperature";
			mCpuTemp[5] = "/sys/devices/platform/omap/omap_temp_sensor.0/temperature";
			mCpuTemp[6] = "/sys/devices/platform/tegra_tmon/temp1_input";
			mCpuTemp[7] = "/sys/kernel/debug/tegra_thermal/temp_tj";
			mCpuTemp[8] = "/sys/devices/platform/s5p-tmu/temperature";
			mCpuTemp[9] = "/sys/class/thermal/thermal_zone0/temp";
			mCpuTemp[10] = "/sys/devices/virtual/thermal/thermal_zone0/temp";
			mCpuTemp[11] = "/sys/class/hwmon/hwmon0/device/temp1_input";
			mCpuTemp[12] = "/sys/devices/virtual/thermal/thermal_zone1/temp";
			mCpuTemp[13] = "/sys/devices/platform/s5p-tmu/curr_temp";
		}

	}

	public static int getCpuTemp(String path) {
		String str = FileUtil.readFileToString(path);
		String[] arrayOfString2 = null;
		try {
			if (str != null) {
				arrayOfString2 = str.split("\\s");
				if (arrayOfString2 != null) {
					if (arrayOfString2.length == 1) {
						if (Float.parseFloat(arrayOfString2[0]) > 100) {
							return (int) Float.parseFloat(arrayOfString2[0]) / 1000;
						}
						return (int) Float.parseFloat(arrayOfString2[0]);
					}
					return (int) Float.parseFloat(arrayOfString2[1]);
				}
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}


		return NOT_AVAILABLE_TEMP;
	}

	public static int getCpuTemp() {
		TempPath mPath = new TempPath();
		mPath.reset();
		int temp = NOT_AVAILABLE_TEMP;
		Temperature temperature = new Temperature(temp, TemperatureUnit.Celsius);
		while (mPath.hasNext()) {
			String pathString = mPath.getNext();
			int t = getCpuTemp(pathString);
			// 需求定义的, 如果CPU温度不是异常的
			temperature.setValue(t);
			if (TemperatureState.isTemperatureValid(temperature)) {
				temp = t;
				break;
			}
		}

		return temp;
	}
}
